import json
from utils.util import detect_op

path_basic_fun_lib = './configs/dicts/basic_function_lib.json'


def read_config(path):
    if path == None:
        return {}, {}, {}, {}, {}, ''
    with open(path, mode='r', encoding='utf-8') as f:
        data = json.load(f)
    var_dict = data[0]
    raw_func_dict = data[1]
    const_dict = data[2]
    tmp_dict = data[3]
    description = data[4]
    with open(path_basic_fun_lib, mode='r', encoding='utf-8') as f:
        basic_func_dict = json.load(f)
    raw_func_dict.update(basic_func_dict)
    func_dict = {}
    # parse original function dictionary
    for func in raw_func_dict.keys():
        raw_func = raw_func_dict[func]["declaration"]
        return_type = raw_func.split(' ')[0]
        func_name, _ = detect_op(' '.join(raw_func.split(' ')[1:]))
        func_dict[func] = {'return_type': return_type, 'output_type': raw_func_dict[func]['output_type'], \
                           'output_dim': raw_func_dict[func]['output_dim'], 'func_name': func_name,
                           'raw_func': raw_func}
    tmp_func = {}
    for func in func_dict.keys():
        if func_dict[func]['func_name'] not in func_dict.keys():
            tmp_func[func_dict[func]['func_name']] = func_dict[func]
    func_dict.update(tmp_func)
    # process const_dict
    if const_dict != {}:
        for var in const_dict.keys():
            if isinstance(const_dict[var], str):
                const_dict[var] = {
                    'name': const_dict[var],
                    'type': 'float32',
                    'dim': '1*1'
                }
            elif isinstance(const_dict[var], dict):
                if 'name' not in const_dict[var].keys():
                    const_dict[var]['name'] = ''
                elif 'type' not in const_dict[var].keys():
                    const_dict[var]['type'] = 'float32'
                elif 'dim' not in const_dict[var].keys():
                    const_dict[var]['dim'] = '1*1'
            if const_dict[var]['name'] == '':
                const_dict[var]['name'] = var
    if tmp_dict != {}:
        for var in tmp_dict.keys():
            if 'name' in tmp_dict[var].keys() and tmp_dict[var]['name'] == '':
                tmp_dict[var]['name'] = var
    return var_dict, func_dict, const_dict, tmp_dict, description


def write_config(path, var_dict, func_dict, const_dict, tmp_dict, out_put, description):
    with open(path, mode='w', encoding='utf-8') as f:
        json.dump([var_dict, func_dict, const_dict, tmp_dict, out_put, description], f)


def read_matrix_config(path):
    if path == None:
        return {}, {}
    with open(path, mode='r', encoding='utf-8') as f:
        data = json.load(f)
    multi_dict = data["multiply"]
    multiScalar_dict = data["multiScalar"]
    transpose_dict = data["transpose"]
    inversion_dict = data["inversion"]
    add_dict = data["add"]
    sub_dict = data["sub"]
    equal_dict = data["equal"]
    vector_norm_dict = data["vector_norm"]
    return add_dict, sub_dict, multi_dict, multiScalar_dict, transpose_dict, inversion_dict, equal_dict, vector_norm_dict


if __name__ == '__main__':
    var_dict = {r'FP_InertialPsi0Dir_Set': {'name': r'sAttDeter.bPermitPsi0DirSet', 'type': 'unint32', 'dim': '1*1'},
                r'F_TargetAtt': {'name': r'sAttDeter.flgTargetAtt', 'type': 'unint32', 'dim': '1*1'},
                r'FP_XToEarthDir': {'name': r'sAttDeter.bPermitXtoEarth', 'type': 'unint32', 'dim': '1*1'},
                r'\Delta\varphi_{m0}': {'name': r'sAttDeter.angleTargetSet[0]', 'type': 'float64', 'dim': '1*1'},
                r'\Delta\theta_{m0}': {'name': r'sAttDeter.angleTargetSet[1]', 'type': 'float64', 'dim': '1*1'},
                r'\Delta\psi_{m0}': {'name': r'sAttDeter.angleTargetSet[2]', 'type': 'float64', 'dim': '1*1'},
                r'F_InertialPsi0Dir': {'name': r'sAttDeter.flgInertialPsi0Dir', 'type': 'unint32', 'dim': '1*1'},
                r'\varphi_{m0}': {'name': r'sAttDeter.anglem0[0]', 'type': 'float64', 'dim': '1*1'},
                r'\theta_{m0}': {'name': r'sAttDeter.anglem0[1]', 'type': 'float64', 'dim': '1*1'},
                r'\psi_{m0}': {'name': r'sAttDeter.anglem0[2]', 'type': 'float64', 'dim': '1*1'},
                r'C_{m0}': {'name': r'sAttDeter.cm0', 'type': 'float64', 'dim': '3*3'},
                r'q_{m0}': {'name': r'sAttDeter.qm0[4]', 'type': 'float64', 'dim': '4*1'}}
    func_dict = {'mod': 'float64 ModPNHP(float64 x, float64 halfperiod)',
                 'dcm': 'void Angle2C(float64 *pOutMA, float64 bi, float64 bj, float64 bk, unint32 ijkHex)',
                 'dcm2q': 'void C2Q(float64 *pOutQ, const float64 *pMat)',
                 'Rx': 'void Rx(float64 *pOutMA, float64 radianX)',
                 'Ry': 'void Ry(float64 *pOutMA, float64 radianY)', 'Rz': 'void Rz(float64 *pOutMA, float64 radianZ)'}
    const_dict = {r'\pi': 'PI'}
    tmp_dict = {r'C_{tmp}': {'type': 'float64', 'dim': '3*3'}}
    out_put = {'name': 'F_InertialPsi0Dir', 'type': 'unint32'}
    description = '姿态机动目标确定的初始化'
    var_dict = dict(sorted(var_dict.items(), key=lambda x: len(x[0]), reverse=True))
    func_dict = dict(sorted(func_dict.items(), key=lambda x: len(x[0]), reverse=True))
    const_dict = dict(sorted(const_dict.items(), key=lambda x: len(x[0]), reverse=True))

    path = '/home/wls/work/Latex2Code/config.json'
    write_config(path, var_dict, func_dict, const_dict, tmp_dict, out_put, description)
    a, b, c, d, e, f = read_config(path)
    print(a)
    print(b)
    print(c)
    print(d)
    print(e)
    print(f)